#include "lib/3d/pvm3dsoftware.h"

#include "lib/3d/pvm3demulation.h"
#include "lib/3d/pvm3demulation_src.h"

using namespace PVM3DSOFTWARENAMESPACE;

PVM3DSOFTWARECLASSNAME::PVM3DSOFTWARECLASSNAME(PVMDEVICE device)
{
	listener = P3DCreateListener(device);
}

PVM3DSOFTWARECLASSNAME::~PVM3DSOFTWARECLASSNAME()
{
	P3DDestroyListener(listener);
}

pvm_int32 PVM3DSOFTWARECLASSNAME::GetRealizationType()
{
	return E_3D_SOFTWARE_FLOAT;
}

void PVM3DSOFTWARECLASSNAME::Update()
{
	P3DUpdate(listener);
}

pvm_bool PVM3DSOFTWARECLASSNAME::Enable()
{
	return P3DEnableListener(listener);
}

void PVM3DSOFTWARECLASSNAME::Disable()
{
	P3DDisableListener(listener);
}

pvm_bool PVM3DSOFTWARECLASSNAME::GetSupportedDistanceModels(pvm_int32* model)
{
	if(model==NULL)
		return false;
	*model = P3DGetDistanceModelsSupport();

	return true;
}

pvm_bool PVM3DSOFTWARECLASSNAME::SetDistanceModel(pvm_int32 model)
{
	return P3DSetDistanceModel(listener, model);
}

pvm_bool PVM3DSOFTWARECLASSNAME::GetDistanceModel(pvm_int32* model)
{
	return P3DGetDistanceModel(listener, model);
}

pvm_bool PVM3DSOFTWARECLASSNAME::ControlEnable(pvm_int32 chanelNum)
{
	return P3DControlEnable(listener, chanelNum);
}

pvm_bool PVM3DSOFTWARECLASSNAME::ControlDisable(pvm_int32 chanelNum)
{
	return P3DControlDisable(listener, chanelNum);
}

pvm_bool PVM3DSOFTWARECLASSNAME::IsControlEnabled(pvm_int32 chanelNum)
{
	return P3DIsControlEnabled(listener, chanelNum);
}

pvm_bool PVM3DSOFTWARECLASSNAME::SetStopOnDistance(pvm_int32 chanelNum, pvm_bool flag)
{
	return P3DSetStopOnDistance(listener, chanelNum, flag);
}

pvm_bool PVM3DSOFTWARECLASSNAME::SetVoiceRate(pvm_int32 chanelNum, pvm_int32 value)
{
	return P3DSetVoiceRate(listener, chanelNum, value);
}

pvm_bool PVM3DSOFTWARECLASSNAME::SetVoiceMaxVolume(pvm_int32 chanelNum, pvm_int32 value)
{
	return P3DSetVoiceMaxVolume(listener, chanelNum, value);
}
//
pvm_bool PVM3DSOFTWARECLASSNAME::GetStopOnDistance(pvm_int32 chanelNum, pvm_bool* flag)
{
	return P3DGetStopOnDistance(listener, chanelNum, flag);
}

pvm_bool PVM3DSOFTWARECLASSNAME::GetVoiceRate(pvm_int32 chanelNum, pvm_int32* value)
{
	return P3DGetVoiceRate(listener, chanelNum, value);
}

pvm_bool PVM3DSOFTWARECLASSNAME::GetVoiceMaxVolume(pvm_int32 chanelNum, pvm_int32* value)
{
	return P3DGetVoiceMaxVolume(listener, chanelNum, value);
}

//////////////////////////////////////////////////////////////////////

pvm_bool PVM3DSOFTWARECLASSNAME::SetListenerPosition_f(float x, float y, float z)
{
	return P3DSetListenerPosition(listener, f2s(x), f2s(y), f2s(z));
}

pvm_bool PVM3DSOFTWARECLASSNAME::SetListenerVelocity_f(float x, float y, float z)
{
	return P3DSetListenerVelocity(listener, f2s(x), f2s(y), f2s(z));
}

pvm_bool PVM3DSOFTWARECLASSNAME::SetListenerOrientation_f(float xFront, float yFront, float zFront, float xTop, float yTop, float zTop)
{
	return P3DSetListenerOrientation(listener, f2s(xFront), f2s(yFront), f2s(zFront), f2s(xTop), f2s(yTop), f2s(zTop));
}

pvm_bool PVM3DSOFTWARECLASSNAME::SetDopplerFactor_f(float factor)
{
	return P3DSetDopplerFactor(listener, f2s(factor));
}

pvm_bool PVM3DSOFTWARECLASSNAME::SetUnitSize_f(float size)
{
	return P3DSetUnitSize(listener, f2s(size));
}

pvm_bool PVM3DSOFTWARECLASSNAME::GetListenerPosition_f(float* x, float* y, float* z)
{
	if(x==NULL || y==NULL || z==NULL)
		return false;

	pvmlib::scalar sX, sY, sZ;
	sX = sY = sZ = 0;
	pvm_bool retVal = P3DGetListenerPosition(listener, &sX, &sY, &sZ);

	*x = (float)(sX);
	*y = (float)(sY);
	*z = (float)(sZ);

	return retVal;
}

pvm_bool PVM3DSOFTWARECLASSNAME::GetListenerVelocity_f(float* x, float* y, float* z)
{
	if(x==NULL || y==NULL || z==NULL)
		return false;

	pvmlib::scalar sX, sY, sZ;
	pvm_bool retVal = P3DGetListenerVelocity(listener, &sX, &sY, &sZ);

	*x = (float)(sX);
	*y = (float)(sY);
	*z = (float)(sZ);

	return retVal;
}

pvm_bool PVM3DSOFTWARECLASSNAME::GetListenerOrientation_f(float* xFront, float* yFront, float* zFront, float* xTop, float* yTop, float* zTop)
{
	if(xFront==NULL || yFront==NULL || zFront==NULL ||
		xTop==NULL || yTop==NULL || zTop==NULL)
		return false;

	pvmlib::scalar sXFront, sYFront, sZFront, sXTop, sYTop, sZTop;
	sXFront = sYFront = sZFront = sXTop = sYTop = sZTop = 0;
	pvm_bool retVal = P3DGetListenerOrientation(listener, &sXFront, &sYFront, &sZFront, &sXTop, &sYTop, &sZTop);

	*zFront = (float)sXFront;
	*yFront = (float)sYFront;
	*zFront = (float)sZFront;
	*xTop = (float)sXTop;
	*yTop = (float)sYTop;
	*zTop = (float)sZTop;

	return retVal;
}

pvm_bool PVM3DSOFTWARECLASSNAME::GetDopplerFactor_f(float* factor)
{
	if(factor==NULL)
		return false;

	pvmlib::scalar sFactor;
	pvm_bool retVal = P3DGetDopplerFactor(listener, &sFactor);

	*factor = (float)(sFactor);

	return retVal;
}

pvm_bool PVM3DSOFTWARECLASSNAME::GetUnitSize_f(float* size)
{
	if(size==NULL)
		return false;

	pvmlib::scalar sSize;
	pvm_bool retVal = P3DGetUnitSize(listener, &sSize);

	*size = (float)(sSize);

	return retVal;
}

pvm_bool PVM3DSOFTWARECLASSNAME::SetVoicePosition_f(pvm_int32 chanelNum, float x, float y, float z)
{
	return P3DSetVoicePosition(listener, chanelNum, f2s(x), f2s(y), f2s(z));
}

pvm_bool PVM3DSOFTWARECLASSNAME::SetVoiceVelocity_f(pvm_int32 chanelNum, float x, float y, float z)
{
	return P3DSetVoiceVelocity(listener, chanelNum, f2s(x), f2s(y), f2s(z));
}

pvm_bool PVM3DSOFTWARECLASSNAME::SetVoiceDirection_f(pvm_int32 chanelNum, float x, float y, float z)
{
	return P3DSetVoiceDirection(listener, chanelNum, f2s(x), f2s(y), f2s(z));
}

pvm_bool PVM3DSOFTWARECLASSNAME::SetVoiceMinDistance_f(pvm_int32 chanelNum, float d)
{
	return P3DSetVoiceMinDistance(listener, chanelNum, f2s(d));
}

pvm_bool PVM3DSOFTWARECLASSNAME::SetVoiceMaxDistance_f(pvm_int32 chanelNum, float d)
{
	return P3DSetVoiceMaxDistance(listener, chanelNum, f2s(d));
}

pvm_bool PVM3DSOFTWARECLASSNAME::SetRolloffFactor_f(pvm_int32 chanelNum, float factor)
{
	return P3DSetRolloffFactor(listener, chanelNum, f2s(factor));
}

pvm_bool PVM3DSOFTWARECLASSNAME::GetVoicePosition_f(pvm_int32 chanelNum, float* x, float* y, float* z)
{
	if(x==NULL || y==NULL || z==NULL)
		return false;

	pvmlib::scalar sX, sY, sZ;
	pvm_bool retVal = P3DGetVoicePosition(listener, chanelNum, &sX, &sY, &sZ);

	*x = (float)(sX);
	*y = (float)(sY);
	*z = (float)(sZ);

	return retVal;
}

pvm_bool PVM3DSOFTWARECLASSNAME::GetVoiceVelocity_f(pvm_int32 chanelNum, float* x, float* y, float* z)
{
	if(x==NULL || y==NULL || z==NULL)
		return false;

	pvmlib::scalar sX, sY, sZ;
	pvm_bool retVal = P3DGetVoiceVelocity(listener, chanelNum, &sX, &sY, &sZ);

	*x = (float)(sX);
	*y = (float)(sY);
	*z = (float)(sZ);

	return retVal;
}


pvm_bool PVM3DSOFTWARECLASSNAME::GetVoiceDirection_f(pvm_int32 chanelNum, float* x, float* y, float* z)
{
	if(x==NULL || y==NULL || z==NULL)
		return false;

	pvmlib::scalar sX, sY, sZ;
	pvm_bool retVal = P3DGetVoiceDirection(listener, chanelNum, &sX, &sY, &sZ);

	*x = (float)(sX);
	*y = (float)(sY);
	*z = (float)(sZ);

	return retVal;
}

pvm_bool PVM3DSOFTWARECLASSNAME::GetVoiceMinDistance_f(pvm_int32 chanelNum, float* d)
{
	if(d==NULL)
		return false;

	pvmlib::scalar sD;
	pvm_bool retVal = P3DGetVoiceMinDistance(listener, chanelNum, &sD);

	*d = (float)(sD);

	return retVal;
}

pvm_bool PVM3DSOFTWARECLASSNAME::GetVoiceMaxDistance_f(pvm_int32 chanelNum, float* d)
{
	if(d==NULL)
		return false;

	pvmlib::scalar sD;
	pvm_bool retVal = P3DGetVoiceMaxDistance(listener, chanelNum, &sD);

	*d = (float)(sD);

	return retVal;
}

pvm_bool PVM3DSOFTWARECLASSNAME::GetRolloffFactor_f(pvm_int32 chanelNum, float* factor)
{
	if(factor==NULL)
		return false;

	pvmlib::scalar sFactor;
	pvm_bool retVal = P3DGetRolloffFactor(listener, chanelNum, &sFactor);

	*factor = (float)(sFactor);

	return retVal;
}

///////////////////////////////////////////////////////////////////////////////////////

pvm_bool PVM3DSOFTWARECLASSNAME::SetListenerPosition_x(pvm_int32 x, pvm_int32 y, pvm_int32 z)
{
	return P3DSetListenerPosition(listener, x2s(x), x2s(y), x2s(z));
}

pvm_bool PVM3DSOFTWARECLASSNAME::SetListenerVelocity_x(pvm_int32 x, pvm_int32 y, pvm_int32 z)
{
	return P3DSetListenerVelocity(listener, x2s(x), x2s(y), x2s(z));
}

pvm_bool PVM3DSOFTWARECLASSNAME::SetListenerOrientation_x(pvm_int32 xFront, pvm_int32 yFront, pvm_int32 zFront, pvm_int32 xTop, pvm_int32 yTop, pvm_int32 zTop)
{
	return P3DSetListenerOrientation(listener, x2s(xFront), x2s(yFront), x2s(zFront), x2s(xTop), x2s(yTop), x2s(zTop));
}

pvm_bool PVM3DSOFTWARECLASSNAME::SetDopplerFactor_x(pvm_int32 factor)
{
	return P3DSetDopplerFactor(listener, x2s(factor));
}

pvm_bool PVM3DSOFTWARECLASSNAME::SetUnitSize_x(pvm_int32 size)
{
	return P3DSetUnitSize(listener, x2s(size));
}

pvm_bool PVM3DSOFTWARECLASSNAME::GetListenerPosition_x(pvm_int32* x, pvm_int32* y, pvm_int32* z)
{
	if(x==NULL || y==NULL || z==NULL)
		return false;

	pvmlib::scalar sX, sY, sZ;
	pvm_bool retVal = P3DGetListenerPosition(listener, &sX, &sY, &sZ);

	*x = s2x(sX).Value();
	*y = s2x(sY).Value();
	*z = s2x(sZ).Value();

	return retVal;
}

pvm_bool PVM3DSOFTWARECLASSNAME::GetListenerVelocity_x(pvm_int32* x, pvm_int32* y, pvm_int32* z)
{
	if(x==NULL || y==NULL || z==NULL)
		return false;

	pvmlib::scalar sX, sY, sZ;
	pvm_bool retVal = P3DGetListenerVelocity(listener, &sX, &sY, &sZ);

	*x = s2x(sX).Value();
	*y = s2x(sY).Value();
	*z = s2x(sZ).Value();

	return retVal;
}

pvm_bool PVM3DSOFTWARECLASSNAME::GetListenerOrientation_x(pvm_int32* xFront, pvm_int32* yFront, pvm_int32* zFront, pvm_int32* xTop, pvm_int32* yTop, pvm_int32* zTop)
{
	if(xFront==NULL || yFront==NULL || zFront==NULL ||
		xTop==NULL || yTop==NULL || zTop==NULL)
		return false;

	pvmlib::scalar sXFront, sYFront, sZFront, sXTop, sYTop, sZTop;
	pvm_bool retVal = P3DGetListenerOrientation(listener, &sXFront, &sYFront, &sZFront, &sXTop, &sYTop, &sZTop);

	*zFront = s2x(sXFront).Value();
	*yFront = s2x(sYFront).Value();
	*zFront = s2x(sZFront).Value();
	*xTop = s2x(sXTop).Value();
	*yTop = s2x(sYTop).Value();
	*zTop = s2x(sZTop).Value();

	return retVal;
}

pvm_bool PVM3DSOFTWARECLASSNAME::GetDopplerFactor_x(pvm_int32* factor)
{
	if(factor==NULL)
		return false;

	pvmlib::scalar sFactor;
	pvm_bool retVal = P3DGetDopplerFactor(listener, &sFactor);

	*factor = s2x(sFactor).Value();

	return retVal;
}

pvm_bool PVM3DSOFTWARECLASSNAME::GetUnitSize_x(pvm_int32* size)
{
	if(size==NULL)
		return false;

	pvmlib::scalar sSize;
	pvm_bool retVal = P3DGetUnitSize(listener, &sSize);

	*size = s2x(sSize).Value();

	return retVal;
}

pvm_bool PVM3DSOFTWARECLASSNAME::SetVoicePosition_x(pvm_int32 chanelNum, pvm_int32 x, pvm_int32 y, pvm_int32 z)
{
	return P3DSetVoicePosition(listener, chanelNum, x2s(x), x2s(y), x2s(z));
}

pvm_bool PVM3DSOFTWARECLASSNAME::SetVoiceVelocity_x(pvm_int32 chanelNum, pvm_int32 x, pvm_int32 y, pvm_int32 z)
{
	return P3DSetVoiceVelocity(listener, chanelNum, x2s(x), x2s(y), x2s(z));
}

pvm_bool PVM3DSOFTWARECLASSNAME::SetVoiceDirection_x(pvm_int32 chanelNum, pvm_int32 x, pvm_int32 y, pvm_int32 z)
{
	return P3DSetVoiceDirection(listener, chanelNum, x2s(x), x2s(y), x2s(z));
}

pvm_bool PVM3DSOFTWARECLASSNAME::SetVoiceMinDistance_x(pvm_int32 chanelNum, pvm_int32 d)
{
	return P3DSetVoiceMinDistance(listener, chanelNum, x2s(d));
}

pvm_bool PVM3DSOFTWARECLASSNAME::SetVoiceMaxDistance_x(pvm_int32 chanelNum, pvm_int32 d)
{
	return P3DSetVoiceMaxDistance(listener, chanelNum, x2s(d));
}

pvm_bool PVM3DSOFTWARECLASSNAME::SetRolloffFactor_x(pvm_int32 chanelNum, pvm_int32 factor)
{
	return P3DSetRolloffFactor(listener, chanelNum, x2s(factor));
}

pvm_bool PVM3DSOFTWARECLASSNAME::GetVoicePosition_x(pvm_int32 chanelNum, pvm_int32* x, pvm_int32* y, pvm_int32* z)
{
	if(x==NULL || y==NULL || z==NULL)
		return false;

	pvmlib::scalar sX, sY, sZ;
	sX = sY = sZ = 0;
	pvm_bool retVal = P3DGetVoicePosition(listener, chanelNum, &sX, &sY, &sZ);

	*x = s2x(sX).Value();
	*y = s2x(sY).Value();
	*z = s2x(sZ).Value();

	return retVal;
}

pvm_bool PVM3DSOFTWARECLASSNAME::GetVoiceVelocity_x(pvm_int32 chanelNum, pvm_int32* x, pvm_int32* y, pvm_int32* z)
{
	if(x==NULL || y==NULL || z==NULL)
		return false;

	pvmlib::scalar sX, sY, sZ;
	pvm_bool retVal = P3DGetVoiceVelocity(listener, chanelNum, &sX, &sY, &sZ);

	*x = s2x(sX).Value();
	*y = s2x(sY).Value();
	*z = s2x(sZ).Value();

	return retVal;
}


pvm_bool PVM3DSOFTWARECLASSNAME::GetVoiceDirection_x(pvm_int32 chanelNum, pvm_int32* x, pvm_int32* y, pvm_int32* z)
{
	if(x==NULL || y==NULL || z==NULL)
		return false;

	pvmlib::scalar sX, sY, sZ;
	pvm_bool retVal = P3DGetVoiceDirection(listener, chanelNum, &sX, &sY, &sZ);

	*x = s2x(sX).Value();
	*y = s2x(sY).Value();
	*z = s2x(sZ).Value();

	return retVal;
}

pvm_bool PVM3DSOFTWARECLASSNAME::GetVoiceMinDistance_x(pvm_int32 chanelNum, pvm_int32* d)
{
	if(d==NULL)
		return false;

	pvmlib::scalar sD;
	pvm_bool retVal = P3DGetVoiceMinDistance(listener, chanelNum, &sD);

	*d = s2x(sD).Value();

	return retVal;
}

pvm_bool PVM3DSOFTWARECLASSNAME::GetVoiceMaxDistance_x(pvm_int32 chanelNum, pvm_int32* d)
{
	if(d==NULL)
		return false;

	pvmlib::scalar sD;
	pvm_bool retVal = P3DGetVoiceMaxDistance(listener, chanelNum, &sD);

	*d = s2x(sD).Value();

	return retVal;
}

pvm_bool PVM3DSOFTWARECLASSNAME::GetRolloffFactor_x(pvm_int32 chanelNum, pvm_int32* factor)
{
	if(factor==NULL)
		return false;

	pvmlib::scalar sFactor;
	pvm_bool retVal = P3DGetRolloffFactor(listener, chanelNum, &sFactor);

	*factor = s2x(sFactor).Value();

	return retVal;
}

#undef PVM3DSOFTWARECLASSNAME
